﻿// -----------------------------------------------------------------------
// <copyright file="IsExpressionAssigned.cs" company="none">
// Copyright (c) 2012 M. Alberti, xanatos(at)live.it
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// </copyright>
// -----------------------------------------------------------------------

namespace FluentSerializer.Utilities
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;

    /// <summary>
    /// 
    /// </summary>
    public class IsExpressionAssigned : ExpressionVisitor
    {
        /// <summary>
        /// 
        /// </summary>
        protected readonly Dictionary<Expression, int> Parameters;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameters"></param>
        protected IsExpressionAssigned(IEnumerable<Expression> parameters)
        {
            this.Parameters = new Dictionary<Expression, int>();

            foreach (var par in parameters)
            {
                this.Parameters.Add(par, 0);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static Dictionary<Expression, int> Check(Expression expression, IEnumerable<Expression> parameters)
        {
            var visitor = new IsExpressionAssigned(parameters);
            visitor.Visit(expression);
            return visitor.Parameters;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public static int Check(Expression expression, Expression parameter)
        {
            var visitor = new IsExpressionAssigned(new[] { parameter });
            visitor.Visit(expression);
            return visitor.Parameters.Values.First();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public override Expression Visit(Expression node)
        {
            if (node != null)
            {
                if (node.NodeType == ExpressionType.Assign || (node.NodeType >= ExpressionType.AddAssign && node.NodeType <= ExpressionType.PostDecrementAssign))
                {
                    int refs;

                    if (this.Parameters.TryGetValue(node, out refs))
                    {
                        this.Parameters[node] = refs + 1;
                    }
                }
            }

            return base.Visit(node);
        }
    }
}